package com.example.aigc_education.common;

import com.example.aigc_education.constant.HttpStatus;
import com.example.aigc_education.exception.RequestRepeatException;
import com.example.aigc_education.utils.ResultUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 全局异常处理器
 */
@Slf4j
@RestControllerAdvice("com.example.aigc_education")
public class GlobalExceptionHandler {


    /**
     * 业务异常
     */
    @ExceptionHandler(BusinessException.class)
    public ResultUtil handleServiceException(BusinessException e, HttpServletRequest request) {
        log.error(e.getMessage(), e);
        Integer code = e.getCode();
        return code != null ? ResultUtil.error(code, e.getMessage()) : ResultUtil.error(e.getMessage());
    }

    /**
     * 重复提交异常
     */
    @ExceptionHandler(RequestRepeatException.class)
    public ResultUtil handleServiceException(RequestRepeatException e, HttpServletRequest request) {
        log.error(e.getMessage(), e);
        Integer code = e.getCode();
        return code != null ? ResultUtil.error(code, e.getMessage()) : ResultUtil.error(e.getMessage());
    }


    /**
     * 参数异常
     */
    @ExceptionHandler(IllegalArgumentException.class)
    public ResultUtil handleIllegalArgumentException(IllegalArgumentException e, HttpServletRequest request) {
        log.error(e.getMessage(), e);
        return ResultUtil.error(e.getMessage());
    }

    /**
     * 参数校验
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultUtil handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        List<ObjectError> errors = ex.getBindingResult().getAllErrors();
        String message = errors.stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(","));
        log.error("参数校验异常:{}", message);
        return ResultUtil.error(HttpStatus.BAD_REQUEST,message);
    }


    /**
     * 参数校验
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ResultUtil handlerConstraintViolationException(ConstraintViolationException ex, HttpServletRequest request) {
        log.error("request {} throw ConstraintViolationException \n", request, ex);
        return ResultUtil.error(HttpStatus.BAD_REQUEST, ex.getMessage());
    }

    /**
     * 请求方式不支持
     * @param ex
     * @return
     */
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class, HttpMediaTypeException.class})
    public ResultUtil handleMethodNotSupportedException(Exception ex) {
        log.error("HttpRequestMethodNotSupportedException \n", ex);
        return ResultUtil.error(HttpStatus.BAD_METHOD, ex.getMessage());
    }

}
